
#ifndef TOKZRGENTR_PARSING_U16STRING_REF_H
#define TOKZRGENTR_PARSING_U16STRING_REF_H
#include<string>
#include"asserts.h"

//#	Like the other text processing libraries.
//#	TokzrGentr also using a string_ref class to
//#	reference the string.
//#	See also StringPiece in google's programming guild.
//#	or string_view in C++17
namespace TokzrGentr
{
	class u16string_ref
	{
	public:
		using char_type = char16_t;
		using size_type = size_t;
	private:
		const char_type *_str;
		size_type _len;
	public:
		u16string_ref(const std::u16string &target)
			:_str(target.c_str()), _len(target.length()) {}
		u16string_ref(const std::u16string &target, size_type len)
			:_str(target.c_str()), _len(len) {}
		u16string_ref(const char_type* str, size_type len)
			:_str(str), _len(len) {}
		template<size_t N>
		u16string_ref(const char_type (&str)[N])
			: _str(str), _len(N-1) {}
		u16string_ref(const u16string_ref &other)
			:_str(other.data()), _len(other.length()) {}
		const char_type* begin() const 
		{
			return _str;
		}
		const char_type* end() const
		{
			return _str + _len;
		}
		std::u16string as_u16string() const
		{
			return std::u16string(_str, _len);
		}
		u16string_ref substr_ref(size_type index_beg, size_type index_end) const
		{
			ASSERT(index_beg < _len);
			ASSERT(index_beg < index_end);
			size_type len = index_end - index_beg;
			ASSERT(len <= _len);
			return u16string_ref(_str + index_beg, len);
		}
		const char_type* data() const
		{
			return _str;
		}
		const char_type *c_str() const
		{
			return data();
		}
		size_type size() const
		{
			return length();
		}
		size_type length() const
		{
			return _len;
		}
		bool empty() const
		{
			return _len == 0;
		}
		void clear()
		{
			_str = nullptr;
			_len = 0;
		}
		void remove_prefix(size_type n)
		{
			ASSERT(n <= _len);
			_str += n;
		}
		void remove_suffix(size_type n)
		{
			ASSERT(n <= _len);
			_len -= n;
		}
		bool operator==(const u16string_ref &other)
		{
			return (length() == other.length()) && (memcmp(c_str(), other.c_str(), length()) == 0);
		}
		bool operator<(const u16string_ref& other)
		{
			return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
		}
		bool operator!=(const u16string_ref &other)
		{
			return (*this == other);
		}
		char_type operator[](size_type index) const
		{
			ASSERT(index < _len);
			return _str[index];
		}
	};
}
#endif // !TOKZRGENTR_PARSING_U16STRING_REF_H
